#include "EpollPoller.h"
#include "Logger.h"
#include "Channel.h"
#include <errno.h>
#include <sys/eventfd.h>
#include <unistd.h>
#include <poll.h>
#include <cstring>
namespace mymuduo {

const int kNew = -1; // channel 的成员 index_ 初始化就是 -1，代表 channel 未添加到 poller 中
const int kAdded = 1; // 代表 channel 已经添加到 poller 中
const int kDeleted = 2; // 代表 channel 已从 poller 中删除

EpollPoller::EpollPoller(EventLoop* loop) 
    : Poller(loop)
    , epollfd_(::epoll_create1(EPOLL_CLOEXEC))
    , events_(kInitEventListSize) 
{
    if(epollfd_ < 0) {  
        LOG_FATAL("epoll_create error:%d \n", errno);
    }
}

EpollPoller::~EpollPoller() {
    ::close(epollfd_);
}

TimeStamp EpollPoller::poll(int timeoutMs, ChannelList* activeChannels) {
    // 实际上应该用 LOG_DEBUG 更合理
    LOG_INFO("func=%s => fd total count%ld\n", __FUNCTION__, channels_.size());
    // 这个函数的作用是等待 epfd 指向的 epoll 实例上的事件，并将发生的事件复制到 events_ 数组中。
    int numEvents = ::epoll_wait(epollfd_,
                                &*events_.begin(), // vector 底层的那个数组的地址
                                static_cast<int>(events_.size()),
                                timeoutMs);
    int saveError = errno;
    TimeStamp now(TimeStamp::now());
    if(numEvents > 0) {
        LOG_INFO("%d events happened\n", numEvents);
        fillActiveChannels(numEvents, activeChannels);
        if(numEvents == events_.size()) {
            events_.resize(events_.size() * 2);
        }
    } else if(numEvents == 0) {
        LOG_DEBUG("%s timeout!\n", __FUNCTION__);
    } else {
        if(saveError != EINTR) {
            errno = saveError;
            LOG_ERROR("EPollPoller::poll() err!\n");
        }
    }
    return now;
}

// channel 的 update/remove 通过调用 eventloop 的 update/remove 来实现
void EpollPoller::updateChannel(Channel *channel) {
    const int index = channel->index();
    LOG_INFO("func=%s => fd=%d events=%d index=%d\n", __FUNCTION__, channel->fd(), channel->event(), index);
    if(index == kNew || index == kDeleted) {
        // 如果这个 channel 是新的或者已经被删除的，代表将 channel 添加到 Poller 中
        int fd = channel->fd();
        if (index == kNew) {
            channels_[fd] = channel;
        }
        channel->set_index(kAdded);
        update(EPOLL_CTL_ADD, channel);
    } else {
        // channel 已经在 poller 中注册过了
        int fd = channel->fd();
        if(channel->isNoneEvent()) {
            // 对任何事件都不感兴趣了，不再监听
            update(EPOLL_CTL_DEL, channel);
            channel->set_index(kDeleted);
        } else {
            update(EPOLL_CTL_MOD, channel);
        }
    }
}

// 从 Poller 中删除 channel
void EpollPoller::removeChannel(Channel *channel) {
    int fd = channel->fd();
    channels_.erase(fd);
    LOG_INFO("func=%s => fd=%d", __FUNCTION__, fd);
    int index = channel->index();
    if(index == kAdded) {
        update(EPOLL_CTL_DEL, channel);
    }
    channel->set_index(kNew); // 设置这个 channel 没有向 poller 添加过
}

// 填写活跃连接
void EpollPoller::fillActiveChannels(int numEvents, ChannelList *activeChannels) const {
    for(int i = 0;i < numEvents; ++i) {
        Channel *channel = static_cast<Channel*> (events_[i].data.ptr);
        channel->setRevents(events_[i].events);
        activeChannels->push_back(channel);
    }
}

// 更新 channel 通道
void EpollPoller::update(int operation, Channel* channel) {
    struct epoll_event event;
    memset(&event, 0, sizeof(event));
    int fd = channel->fd();
    event.events = channel->event();
    // event.data.fd = fd;
    event.data.ptr = channel;
    // 还是调用 epoll_ctl
    if(::epoll_ctl(epollfd_, operation, fd, &event) < 0) {
        if(operation == EPOLL_CTL_DEL) {
            LOG_ERROR("func=%s => epoll_ctl del error:%d", __FUNCTION__, errno);
        } else {
            LOG_FATAL("func=%s => epoll_ctl add/mod error:%d", __FUNCTION__, errno);
        }
    }
}


}